#include "lcd_init.h"

spi_init_type spi_init_struct;

void lcd_gpio_init(void)
{
  gpio_init_type gpio_init_struct;
  gpio_default_para_init(&gpio_init_struct);

  crm_periph_clock_enable(LCD_CS_GPIO_CRM_CLK, TRUE);
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_pins = LCD_CS_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(LCD_CS_GPIO, &gpio_init_struct);
  LCD_CS_Set();

  crm_periph_clock_enable(LCD_DC_GPIO_CRM_CLK, TRUE);
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_pins = LCD_DC_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(LCD_DC_GPIO, &gpio_init_struct);

  crm_periph_clock_enable(LCD_BLK_GPIO_CRM_CLK, TRUE);
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_pins = LCD_BLK_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(LCD_BLK_GPIO, &gpio_init_struct);

  crm_periph_clock_enable(LCD_RST_GPIO_CRM_CLK, TRUE);
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_pins = LCD_RST_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(LCD_RST_GPIO, &gpio_init_struct);
  LCD_RES_Set();

  crm_periph_clock_enable(LCD_CLK_GPIO_CRM_CLK, TRUE);
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_pins = LCD_CLK_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(LCD_CLK_GPIO, &gpio_init_struct);
  gpio_pin_mux_config(LCD_CLK_GPIO, LCD_CLK_SOURCE, LCD_CLK_MUX);

  crm_periph_clock_enable(LCD_DAT_GPIO_CRM_CLK, TRUE);
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_pins = LCD_DAT_PIN;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(LCD_DAT_GPIO, &gpio_init_struct);
  gpio_pin_mux_config(LCD_DAT_GPIO, LCD_DAT_SOURCE, LCD_DAT_MUX);

  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_pins = GPIO_PINS_15;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  gpio_init(GPIOA, &gpio_init_struct);
  gpio_bits_set(GPIOA, GPIO_PINS_15);
}

void lcd_spi_config(void)
{
  dma_init_type dma_init_struct;

  crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
  dma_reset(DMA1_CHANNEL1);

  dma_default_para_init(&dma_init_struct);
  dmamux_enable(DMA1, TRUE);
  dmamux_init(DMA1MUX_CHANNEL1, DMAMUX_DMAREQ_ID_SPI1_TX);

  dma_init_struct.buffer_size = 0;
  dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
  dma_init_struct.memory_base_addr = (uint32_t)0x0;
  dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
  dma_init_struct.memory_inc_enable = TRUE;
  dma_init_struct.peripheral_base_addr = (uint32_t)(&SPI1->dt);
  dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
  dma_init_struct.peripheral_inc_enable = FALSE;
  dma_init_struct.priority = DMA_PRIORITY_LOW;
  dma_init_struct.loop_mode_enable = FALSE;
  dma_init(DMA1_CHANNEL1, &dma_init_struct);

  crm_periph_clock_enable(CRM_SPI1_PERIPH_CLOCK, TRUE);
  spi_i2s_reset(SPI1);

  spi_default_para_init(&spi_init_struct);
  spi_init_struct.transmission_mode = SPI_TRANSMIT_HALF_DUPLEX_TX;
  spi_init_struct.master_slave_mode = SPI_MODE_MASTER;
  spi_init_struct.mclk_freq_division = SPI_MCLK_DIV_4;
  spi_init_struct.first_bit_transmission = SPI_FIRST_BIT_MSB;
  spi_init_struct.frame_bit_num = SPI_FRAME_8BIT;
  spi_init_struct.clock_polarity = SPI_CLOCK_POLARITY_HIGH;
  spi_init_struct.clock_phase = SPI_CLOCK_PHASE_2EDGE;
  spi_init_struct.cs_mode_selection = SPI_CS_SOFTWARE_MODE;
  spi_init(SPI1, &spi_init_struct);
  spi_i2s_dma_transmitter_enable(SPI1, TRUE);
  spi_enable(SPI1, TRUE);
}

void LCD_Write_Bus(u8 dat)
{
  LCD_CS_Clr();
  DMA1_CHANNEL1->dtcnt_bit.cnt = 1;
  DMA1_CHANNEL1->maddr = (uint32_t)&dat;

  dma_channel_enable(DMA1_CHANNEL1, TRUE);
  while(spi_i2s_flag_get(SPI1, SPI_I2S_BF_FLAG) == SET);
  dma_channel_enable(DMA1_CHANNEL1, FALSE);
  LCD_CS_Set();
}

void LCD_WR_DATA8(u8 dat)
{
  LCD_Write_Bus(dat);
}

void LCD_WR_DATA(u16 dat)
{
  LCD_Write_Bus(dat >> 8);
  LCD_Write_Bus(dat);
}

void LCD_WR_REG(u8 dat)
{
  LCD_DC_Clr();//д����
  LCD_Write_Bus(dat);
  LCD_DC_Set();//д����
}

void LCD_Address_Set(u16 x1, u16 y1, u16 x2, u16 y2)
{
  if(USE_HORIZONTAL == 0)
  {
    LCD_WR_REG(0x2a);//�е�ַ����
    LCD_WR_DATA(x1);
    LCD_WR_DATA(x2);
    LCD_WR_REG(0x2b);//�е�ַ����
    LCD_WR_DATA(y1);
    LCD_WR_DATA(y2);
    LCD_WR_REG(0x2c);//������д
  }
  else if(USE_HORIZONTAL == 1)
  {
    LCD_WR_REG(0x2a);//�е�ַ����
    LCD_WR_DATA(x1);
    LCD_WR_DATA(x2);
    LCD_WR_REG(0x2b);//�е�ַ����
    LCD_WR_DATA(y1 + 80);
    LCD_WR_DATA(y2 + 80);
    LCD_WR_REG(0x2c);//������д
  }
  else if(USE_HORIZONTAL == 2)
  {
    LCD_WR_REG(0x2a);//�е�ַ����
    LCD_WR_DATA(x1);
    LCD_WR_DATA(x2);
    LCD_WR_REG(0x2b);//�е�ַ����
    LCD_WR_DATA(y1);
    LCD_WR_DATA(y2);
    LCD_WR_REG(0x2c);//������д
  }
  else
  {
    LCD_WR_REG(0x2a);//�е�ַ����
    LCD_WR_DATA(x1 + 80);
    LCD_WR_DATA(x2 + 80);
    LCD_WR_REG(0x2b);//�е�ַ����
    LCD_WR_DATA(y1);
    LCD_WR_DATA(y2);
    LCD_WR_REG(0x2c);//������д
  }
}

void LCD_Init(void)
{
  lcd_gpio_init();
  lcd_spi_config();
	
	LCD_RES_Clr();//��λ
	delay_ms(100);
	LCD_RES_Set();
	delay_ms(100);
	
		//************* Start Initial Sequence **********//
	LCD_WR_REG(0x11); //Sleep out 
	delay_ms(120);              //Delay 120ms 
	//************* Start Initial Sequence **********// 
	LCD_WR_REG(0x36);
	if(USE_HORIZONTAL==0)LCD_WR_DATA8(0x00);
	else if(USE_HORIZONTAL==1)LCD_WR_DATA8(0xC0);
	else if(USE_HORIZONTAL==2)LCD_WR_DATA8(0x70);
	else LCD_WR_DATA8(0xA0);

	LCD_WR_REG(0x3A);     
	LCD_WR_DATA8(0x05);   

	LCD_WR_REG(0xB2);     
	LCD_WR_DATA8(0x1F);   
	LCD_WR_DATA8(0x1F);   
	LCD_WR_DATA8(0x00);   
	LCD_WR_DATA8(0x33);   
	LCD_WR_DATA8(0x33);   

	LCD_WR_REG(0xB7);     
	LCD_WR_DATA8(0x35);   

	LCD_WR_REG(0xBB);     
	LCD_WR_DATA8(0x2B);   //2b

	LCD_WR_REG(0xC0);     
	LCD_WR_DATA8(0x2C);   

	LCD_WR_REG(0xC2);     
	LCD_WR_DATA8(0x01);   

	LCD_WR_REG(0xC3);     
	LCD_WR_DATA8(0x0F);   

	LCD_WR_REG(0xC4);     
	LCD_WR_DATA8(0x20);   //VDV, 0x20:0v

	LCD_WR_REG(0xC6);     
	LCD_WR_DATA8(0x13);   //0x13:60Hz   

	LCD_WR_REG(0xD0);     
	LCD_WR_DATA8(0xA4);   
	LCD_WR_DATA8(0xA1);   

	LCD_WR_REG(0xD6);     
	LCD_WR_DATA8(0xA1);   //sleep in��gate���ΪGND

	LCD_WR_REG(0xE0);     
	LCD_WR_DATA8(0xF0);   
	LCD_WR_DATA8(0x04);   
	LCD_WR_DATA8(0x07);   
	LCD_WR_DATA8(0x04);   
	LCD_WR_DATA8(0x04);   
	LCD_WR_DATA8(0x04);   
	LCD_WR_DATA8(0x25);   
	LCD_WR_DATA8(0x33);   
	LCD_WR_DATA8(0x3C);   
	LCD_WR_DATA8(0x36);   
	LCD_WR_DATA8(0x14);   
	LCD_WR_DATA8(0x12);   
	LCD_WR_DATA8(0x29);   
	LCD_WR_DATA8(0x30);   

	LCD_WR_REG(0xE1);     
	LCD_WR_DATA8(0xF0);   
	LCD_WR_DATA8(0x02);   
	LCD_WR_DATA8(0x04);   
	LCD_WR_DATA8(0x05);   
	LCD_WR_DATA8(0x05);   
	LCD_WR_DATA8(0x21);   
	LCD_WR_DATA8(0x25);   
	LCD_WR_DATA8(0x32);   
	LCD_WR_DATA8(0x3B);   
	LCD_WR_DATA8(0x38);   
	LCD_WR_DATA8(0x12);   
	LCD_WR_DATA8(0x14);   
	LCD_WR_DATA8(0x27);   
	LCD_WR_DATA8(0x31);   

	LCD_WR_REG(0xE4);     
	LCD_WR_DATA8(0x1D);   //ʹ��240��gate  (N+1)*8
	LCD_WR_DATA8(0x00);   //�趨gate���λ��
	LCD_WR_DATA8(0x00);   //��gateû������ʱ��bit4(TMG)��Ϊ0

	LCD_WR_REG(0x21);     

	LCD_WR_REG(0x29);
} 